//
//  dominionSetupTests.c
//  Dominion
//
//  Created by Team 10, Eric Hook, Michael Wyatt.
//  CS372 Software Engineering 2
//

#include "headers.h"

#define NUM_TESTS 2

struct gameState *G;
struct gameState *Gpost;
struct gameState *Gpre;
int i, numPlayers ;
//static int cardToTest = sea_hag;
int seed = 100;



void setUpGameState(){
    G     = malloc(sizeof(struct gameState));
    Gpost = malloc(sizeof(struct gameState));
    Gpre  = malloc(sizeof(struct gameState));
    srand((int)time(NULL));//time doesn't update fast enough - need fix
    //seed = seed + 1;
    gameStateRandomizer(G, seed);   // setup a reasonable random game state with expected num players are reasonable arguements for game
    memcpy (Gpost, G, sizeof(struct gameState));
    memcpy (Gpre,  G, sizeof(struct gameState));
}

/* based upon random, reasonable game state asserts that the number of each type of card is distributed in the correct number according to rules (black box)*/
void checkInitialGameState(){
    assert(G->numPlayers <= MAX_PLAYERS);
    assert(G->numPlayers >= 2);
    if (numPlayers == 2) {
        assert (G->supplyCount[curse] == 10);
        assert (G->supplyCount[estate] = 8);
        assert (G->supplyCount[duchy] = 8);
        assert (G->supplyCount[province] = 8);
    }
    if (numPlayers == 3) {
        assert (G->supplyCount[curse] == 20);
        assert (G->supplyCount[estate] = 12);
        assert (G->supplyCount[duchy] = 12);
        assert (G->supplyCount[province] = 12);
    }
    if (numPlayers == 4) {
        assert (G->supplyCount[curse] == 30);
        assert (G->supplyCount[estate] = 12);
        assert (G->supplyCount[duchy] = 12);
        assert (G->supplyCount[province] = 12);
    }
    assert (G->supplyCount[copper] == (60 - (7 * G->numPlayers) ) );
    assert (G->supplyCount[silver] == 40);
    assert (G->supplyCount[gold] == 30);
}

/*calls shuffle deck and check to see that the content of the post shuffle cards exactly matches the pre-shuffle cards*/
void checkShuffle(){
    
    int compare(const void* a, const void* b);
    int ret = shuffle(0,Gpost);
    
    if (G->deckCount[0] > 0) {
        assert (ret != -1);
        qsort ((void*)(Gpost->deck[0]), Gpost->deckCount[0], sizeof(int), compare);
        qsort ((void*)(Gpre->deck[0]), Gpre->deckCount[0], sizeof(int), compare);
    } else
        assert (ret == -1);
    
    assert(memcmp(Gpost, Gpre, sizeof(struct gameState)) == 0);
}

/*buys a random card and asserts that supply, buys, coins, and hand count are as expected and that it does not buy a card if no selected card to buy or insufficient coins*/
void checkBuyCard(){
    int randSupplyCard = rand() % 10 + 7;
    int preSupplyCardCount = supplyCount(randSupplyCard, G);
    int preNumBuys = G->numBuys;
    int preNumCoins = G->coins;
    int preHandCount = G->handCount[whoseTurn(G)] ;
    buyCard(randSupplyCard, G);
    int postSupplyCardCount = supplyCount(randSupplyCard, G);
    int postNumBuys = G->numBuys;
    int postNumCoins = G->coins;
    int postHandCount = G->handCount[whoseTurn(G)] ;
    if (preSupplyCardCount == 0){                                           // not any cards to buy
        assert (preSupplyCardCount == 0 && postSupplyCardCount == 0);
        assert (preNumBuys == postNumBuys);
        assert (preNumCoins == postNumCoins);
        assert (preHandCount == postHandCount);
    }
    if (G->coins < getCost(randSupplyCard)){                                // not enough cins to buy card
        assert (preSupplyCardCount == postSupplyCardCount);
        assert (preNumBuys == postNumBuys);
        assert (preNumCoins == postNumCoins);
        assert (preHandCount == postHandCount);
    }
    else {
        assert (preSupplyCardCount == postSupplyCardCount + 1);
        assert (preNumBuys == postNumBuys + 1);
        assert (preNumCoins == postNumCoins + getCost(randSupplyCard));
        assert (preHandCount == postHandCount -1);
    }
}

/* simple check to check if numHandCards returns correct number of cards in whoseTurn for handCount */
void checkNumHandCards(){
    assert (G->handCount[whoseTurn(G)] == numHandCards(G));
}

/* simple check to check if handCard() returns correct card for random player by checking deck array */
void checkHandCard() {
    memcpy (Gpost, G, sizeof(struct gameState));
    //memcpy (Gpre,  G, sizeof(struct gameState));
    int randPlayer = rand() % (Gpost->numPlayers);
    int whoseTurnPre = Gpost->whoseTurn;
    Gpost->whoseTurn = randPlayer;
    int handCountTemp = Gpost->handCount[randPlayer];
    int randHandCard = rand() % handCountTemp;
    assert(Gpost->hand[randPlayer][randHandCard]  == handCard(randHandCard, Gpost));
    Gpost->whoseTurn = whoseTurnPre;  // reset to to original setting
    memcpy (Gpost, G, sizeof(struct gameState)); // reset Gpost for reuse later
    //memcpy (Gpre,  G, sizeof(struct gameState));
}

/* simple check to see if manually set supply is returned correctly using supplyCount() */
void checkSupplyCount() {
    int randSupplyCard = rand() % 10 + 7;
    assert (G->supplyCount[randSupplyCard] == supplyCount(randSupplyCard, G));
}

/* check to see if correct number of cards retunred by fullDeckCount(). Adds up all cards that are NOT the random card and check to see that the full count minus the fullDeckCount() is equal to this difference */
void checkFullDeckCount() {
    memcpy (Gpost, G, sizeof(struct gameState));
    int count = 0;
    int randCard = rand() % 16;
    int randPlayer = rand() % (Gpost->numPlayers);
    //int handCards, deckCards, discardCards;
    for (i = 0; i < Gpost->deckCount[randPlayer]; i++)
    {
        if (Gpost->deck[randPlayer][i] != randCard) count++;
    }
    
    for (i = 0; i < Gpost->handCount[randPlayer]; i++)
    {
        if (Gpost->hand[randPlayer][i] != randCard) count++;
    }
    
    for (i = 0; i < Gpost->discardCount[randPlayer]; i++)
    {
        if (Gpost->discard[randPlayer][i] != randCard) count++;
    }
    // add up ALL cards, find all cards NOT the random card and the difference should be the value returned by fullDeckCount;
    assert ( fullDeckCount(randPlayer, randCard, Gpost) == Gpost->deckCount[randPlayer] + Gpost->handCount[randPlayer] +  Gpost->discardCount[randPlayer] - count) ;
    memcpy (Gpost, G, sizeof(struct gameState));
}

/* checks whoseTurn(), ends a turn() and check that turn correctly assigned to next player or back to player 0 if last player */
void checkWhoseTurn(){
    memcpy (Gpost, G, sizeof(struct gameState));
    memcpy (Gpre,  G, sizeof(struct gameState));
    int turnStart = whoseTurn(Gpost);
    endTurn(Gpost);
    int turnEnd = whoseTurn(Gpost);
    if (turnStart < numPlayers - 1) assert(turnEnd == turnStart + 1);
    if (turnStart == numPlayers - 1) assert(turnEnd == 0);
    memcpy (Gpost, G, sizeof(struct gameState));  // reset/copy game state
    memcpy (Gpre,  G, sizeof(struct gameState));
}

/* checks that endTurn correctly moves turn to next player, and resets outpostsPlayed, phase, numActions, numBuys, playedCardCount, and new player draws a hand of 5 cards */
void checkEndTurn(){
    memcpy (Gpost, G, sizeof(struct gameState));
    memcpy (Gpre,  G, sizeof(struct gameState));
    int turnStart = whoseTurn(Gpost);
    endTurn(Gpost);
    int turnEnd = whoseTurn(Gpost);
    if (turnStart < numPlayers - 1) assert(turnEnd == turnStart + 1);
    if (turnStart == numPlayers - 1) assert(turnEnd == 0);
    assert (Gpost->outpostPlayed == 0);
    assert (Gpost->phase == 0);
    assert (Gpost->numActions == 1);
    //assert (Gpost->coins == 0); // this value is immediately reset by new player so is only 0 for a brief moment
    assert (Gpost->numBuys == 1);
    assert (Gpost->playedCardCount == 0);
    //assert (Gpost->handCount[Gpost->whoseTurn] == 0);  // this one is a bit odd, this game always resets hand at end turn and draws new cards at beginning
    if ( Gpost->deckCount[whoseTurn(Gpost)] + Gpost->discardCount[whoseTurn(Gpost)]  >= 5 ) assert(Gpost->handCount[whoseTurn(Gpost)] == 5);
    memcpy (Gpost, G, sizeof(struct gameState));   // reset/copy game state
    memcpy (Gpre,  G, sizeof(struct gameState));
}

/* checks that isGameOver() correctly recognizes game over condition of no provice or three empty Kingdom card piles */
void checkIsGameOver(){
    memcpy (Gpost, G, sizeof(struct gameState));
    //memcpy (Gpre,  G, sizeof(struct gameState));
    Gpost->supplyCount[province] = 1;
    for (i = 0; i <= 25; i++) // set every card 0 to 25 (26 total to one)
    {
        Gpost->supplyCount[i] = 1;
    }
    assert(isGameOver(Gpost) == 0);
    Gpost->supplyCount[province] = 0;
    assert(isGameOver(Gpost) == 1);
    Gpost->supplyCount[province] = 1;
    int randCardDeplete1 = rand() % 20 + 7;
    int randCardDeplete2 = rand() % 20 + 7;
    while (randCardDeplete2  == randCardDeplete1) {  // make sure they aren't the same
        randCardDeplete2 = rand() % 20 + 7;
    }
    Gpost->supplyCount[randCardDeplete1] = 0;
    Gpost->supplyCount[randCardDeplete2] = 0;
    assert(isGameOver(Gpost) == 0);
    int randCardDeplete3 = rand() % 20 + 7;
    while (randCardDeplete3  == randCardDeplete1 || randCardDeplete3 == randCardDeplete2) {  // make sure they aren't the same
        randCardDeplete3 = rand() % 20 + 7;
    }
    Gpost->supplyCount[randCardDeplete3] = 0;
    //Gpost->supplyCount[26] = 0;
    assert(isGameOver(Gpost) == 1);
    memcpy (Gpost, G, sizeof(struct gameState));   // reset/copy game state
    //memcpy (Gpre,  G, sizeof(struct gameState));
}

/* clears and then fills hand, deck and then discard with passes of each of the scoring cards and asserts that each scoreFor() returns the correct score for a random player  */
void checkScoreFor(){
    memcpy (Gpost, G, sizeof(struct gameState));
    int randPlayer = rand() % Gpost->numPlayers;
    const int numScoreCards = 6;
    int scoreCards[numScoreCards] = {curse, estate, duchy, province, great_hall, gardens};
    int totalNumberCards = Gpost->handCount[randPlayer] + Gpost->deckCount[randPlayer] + Gpost->discardCount[randPlayer];
    
    // stack random player hand with known scoring cards and check score
    for (int card = 0; card < numScoreCards; card++){
        
        // reset hand, deck, discard
        for (i = 0; i <= G->handCount[randPlayer]; i++)
        {
            Gpost->hand[randPlayer][i] = -1;
        }
        for (i = 0; i < G->discardCount[randPlayer]; i++)
        {
            Gpost->discard[randPlayer][i] = -1;
        }
        for (i = 0; i < G->deckCount[randPlayer]; i++) //
        {
            Gpost->deck[randPlayer][i] = -1;
        }
        
        // fill hand, deck, discard
        for (i = 0; i <= G->handCount[randPlayer]; i++)
        {
            Gpost->hand[randPlayer][i] = scoreCards[card];
        }

        if (scoreCards[card] == curse) printf("curse\n");
        if (scoreCards[card] == curse) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->handCount[randPlayer]) * -1 ) );
        if (scoreCards[card] == estate) printf("estate\n");
        if (scoreCards[card] == estate) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->handCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == duchy) printf("duchy\n");
        if (scoreCards[card] == duchy) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->handCount[randPlayer]) * 3 ) );
        if (scoreCards[card] == province) printf("province\n");
        if (scoreCards[card] == province) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->handCount[randPlayer]) * 6 ) );
        if (scoreCards[card] == great_hall) printf("great hall\n");
        if (scoreCards[card] == great_hall) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->handCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == gardens) printf("gardens scoreFor = %i / fullDeckCount gardens = %i \n", scoreFor(randPlayer, Gpost), fullDeckCount(randPlayer, gardens, Gpost) );
        if (scoreCards[card] == gardens) assert ( scoreFor(randPlayer, Gpost) == ( fullDeckCount(randPlayer, gardens, Gpost) * (totalNumberCards / 10)) ) ;
    }
    memcpy (Gpost, G, sizeof(struct gameState));
    
    // stack random player discard with known scoring cards and check score
    for (int card = 0; card < numScoreCards; card++){
        
        // reset hand, deck, discard
        for (i = 0; i <= Gpost->handCount[randPlayer]; i++)
        {
            Gpost->hand[randPlayer][i] = -1;
        }
        for (i = 0; i <= Gpost->discardCount[randPlayer]; i++)
        {
            Gpost->discard[randPlayer][i] = -1;
        }
        for (i = 0; i <= Gpost->deckCount[randPlayer]; i++) //
        {
            Gpost->deck[randPlayer][i] = -1;
        }
        
        // fill hand, deck, discard
        for (i = 0; i <= Gpost->deckCount[randPlayer]; i++)
        {
            Gpost->deck[randPlayer][i] = scoreCards[card];
        }

        if (scoreCards[card] == curse) printf("curse\n");
        if (scoreCards[card] == curse) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->deckCount[randPlayer]) * -1 ) );
        if (scoreCards[card] == estate) printf("estate\n");
        if (scoreCards[card] == estate) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->deckCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == duchy) printf("duchy\n");
        if (scoreCards[card] == duchy) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->deckCount[randPlayer]) * 3 ) );
        if (scoreCards[card] == province) printf("province\n");
        if (scoreCards[card] == province) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->deckCount[randPlayer]) * 6 ) );
        if (scoreCards[card] == great_hall) printf("great hall\n");
        if (scoreCards[card] == great_hall) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->deckCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == gardens) printf("gardens scorefor = %i\n",scoreFor(randPlayer, Gpost) );
        if (scoreCards[card] == gardens) assert ( scoreFor(randPlayer, Gpost) == ( fullDeckCount(randPlayer, gardens, Gpost ) * (totalNumberCards / 10)) ) ;
    }
    
    memcpy (Gpost, G, sizeof(struct gameState));
    
    // stack random player deck with known scoring cards and check score
    for (int card = 0; card < numScoreCards; card++){
        
        // reset hand, deck, discard
        for (i = 0; i <= Gpost->handCount[randPlayer]; i++)
        {
            Gpost->hand[randPlayer][i] = -1;
        }
        for (i = 0; i < Gpost->discardCount[randPlayer]; i++)
        {
            Gpost->discard[randPlayer][i] = -1;
        }
        for (i = 0; i < Gpost->deckCount[randPlayer]; i++) //
        {
            Gpost->deck[randPlayer][i] = -1;
        }
        
        // fill hand, deck, discard
        for (i = 0; i <= Gpost->handCount[randPlayer]; i++)
        {
            Gpost->discard[randPlayer][i] = scoreCards[card];
        }
        //printf("card == %i\n", scoreCards[card]);
        
        //printf("scorefor  %i   player  %i / num cards %i ", scoreFor(randPlayer, Gpost), randPlayer, Gpost->handCount[randPlayer]);
        if (scoreCards[card] == curse) printf("curse\n");
        if (scoreCards[card] == curse) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->discardCount[randPlayer]) * -1 ) );
        if (scoreCards[card] == estate) printf("estate\n");
        if (scoreCards[card] == estate) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->discardCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == duchy) printf("duchy\n");
        if (scoreCards[card] == duchy) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->discardCount[randPlayer]) * 3 ) );
        if (scoreCards[card] == province) printf("province\n");
        if (scoreCards[card] == province) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->discardCount[randPlayer]) * 6 ) );
        if (scoreCards[card] == great_hall) printf("great hall\n");
        if (scoreCards[card] == great_hall) assert ( scoreFor(randPlayer, Gpost) == ( (Gpost->discardCount[randPlayer]) * 1 ) );
        if (scoreCards[card] == gardens) printf("gardens\n");
        if (scoreCards[card] == gardens) assert ( scoreFor(randPlayer, Gpost) == ( fullDeckCount(randPlayer, gardens, Gpost ) * (totalNumberCards / 10)) ) ;
    }
    memcpy (Gpost, G, sizeof(struct gameState));

}

 /* simple check to ensure winner is one of the valid players based upon numPlayers */
void checkGetWinners(){
    /* examining the code seems correct */
    int players[MAX_PLAYERS];
    assert(getWinners(players, Gpost) >= 0 && getWinners(players, Gpost) <= Gpost->numPlayers); // just checks to see valid player num returned based upon number game players
}

/* checks to see that card counts for hand, discard and deck are correct after calling drawCard()  */
void checkDrawCard(){
    memcpy (Gpost, G, sizeof(struct gameState));
    int randPlayer = rand() % (Gpost->numPlayers);
    //int randCard = rand() % 16;
    int preHandCount = Gpost->handCount[randPlayer];
    int postHandCount = 0;
    int preDeckCount = Gpost->deckCount[randPlayer];
    int postDeckCount = 0;
    int preDiscardCount = Gpost->discardCount[randPlayer];
    int postDiscardCount = 0;
    drawCard(randPlayer, Gpost);
    postHandCount = (int)Gpost->handCount[randPlayer];
    postDeckCount = (int)Gpost->deckCount[randPlayer];
    postDiscardCount = (int)Gpost->discardCount[randPlayer];
    if (Gpost->deckCount[randPlayer] <= 0){
        assert((int)Gpost->deckCount == preDiscardCount); // deck was empty so should shuffle and move to deck
        assert((int)Gpost->discardCount[randPlayer] == 0); // discards should be reccled back into deck
    }
    assert(preHandCount == postHandCount - 1);  // post hand should have 1 more card
    assert(preDeckCount == postDeckCount + 1);  // post deck should have 1 less card
    assert(preDiscardCount == postDiscardCount); // unless deck shuffled discard should stay same
}

/* a simple check to make sure the cost always return correct expected values (black box) */
void checkGetCost() {

    assert(getCost(curse) == 0);
    assert(getCost(estate) == 2);
    assert(getCost(duchy) == 5);
    assert(getCost(province) == 8);
    assert(getCost(copper) == 0);
    assert(getCost(silver) == 3);
    assert(getCost(gold) == 6);
    assert(getCost(adventurer) == 6);
    assert(getCost(council_room) == 5);
    assert(getCost(gardens) == 4);
    assert(getCost(mine) == 5);
    assert(getCost(remodel) == 4);
    assert(getCost(smithy) == 4);
    assert(getCost(village) == 3);
    assert(getCost(baron) == 4);
    assert(getCost(great_hall) == 3);
    assert(getCost(minion) == 5);
    assert(getCost(steward) == 3);
    assert(getCost(tribute) == 5);
    assert(getCost(ambassador) == 3);
    assert(getCost(cutpurse) == 4);
    assert(getCost(embargo) == 2);
    assert(getCost(outpost) == 5);
    assert(getCost(salvager) == 4);
    assert(getCost(sea_hag) == 4);
    assert(getCost(treasure_map) == 4);

}

/* checks that hand, cardsPlayed, and playedCardCount behave correctly when discardCard() called (with and without trash flag set) and that when card is discarded that it is the last one added to playedCards[player][card] */
void checkDiscardCard() {
    memcpy (Gpost, G, sizeof(struct gameState));
    int randPlayer = rand() % (Gpost->numPlayers);
    int randHandPos = rand() % (Gpost->handCount[randPlayer]);
    int trashFlag = 1;
    int preHandCount = Gpost->handCount[randPlayer];
    int postHandCount = 0;
    int preDeckCount = Gpost->deckCount[randPlayer];
    int postDeckCount = 0;
    int preDiscardCount = Gpost->discardCount[randPlayer];
    int postDiscardCount = 0;
    int prePlayedCardCount = Gpost->playedCardCount;
    int postPlayedCardCount = 0;
    
    discardCard(randHandPos, randPlayer, Gpost, trashFlag);
    
    postHandCount = (int)Gpost->handCount[randPlayer];
    postDeckCount = (int)Gpost->deckCount[randPlayer];
    postDiscardCount = (int)Gpost->discardCount[randPlayer];
    postPlayedCardCount = (int)Gpost->playedCardCount;
    
    if (trashFlag == 1) {
        assert(preHandCount == postHandCount + 1 ); // one less card in hand
        assert(preDeckCount == postDeckCount); // card was trashed NOT added to deck
        assert(preDiscardCount == postDiscardCount); // card was trashed NOT discarded
        assert (prePlayedCardCount == postPlayedCardCount); // card was trashed NOT played
    }
    
    memcpy (Gpost, G, sizeof(struct gameState));
    randPlayer = rand() % (Gpost->numPlayers);
    randHandPos = rand() % (Gpost->handCount[randPlayer]);
    int randCardSelected = Gpost->hand[randPlayer][randHandPos];
    trashFlag = 0;
    
    discardCard(randHandPos, randPlayer, Gpost, trashFlag);
    
    postHandCount = (int)Gpost->handCount[randPlayer];
    postDeckCount = (int)Gpost->deckCount[randPlayer];
    postDiscardCount = (int)Gpost->discardCount[randPlayer];
    postPlayedCardCount = (int)Gpost->playedCardCount;
    
    assert(preHandCount == postHandCount + 1 ); // one less card in hand
    assert(preDeckCount == postDeckCount); // card NOT added to deck
    assert(preDiscardCount == postDiscardCount ); //
    assert(prePlayedCardCount == postPlayedCardCount - 1); // card was played NOT trashed
    assert( Gpost->playedCards[(Gpost->playedCardCount) - 1 ] == randCardSelected);  // checks to see if card in rand position is the last card added to playedCards

}


/* check to see that card from supply added to player's 1)discard 2)deck or 3)hand */
void checkGainCard(){
    memcpy (Gpost, G, sizeof(struct gameState));
    int randPlayer = rand() % (Gpost->numPlayers);
    int randSupplyPos = rand() % 10 + 7;
    int preHandCount = Gpost->handCount[randPlayer];
    int postHandCount = 0;
    int preDeckCount = Gpost->deckCount[randPlayer];
    int postDeckCount = 0;
    int preDiscardCount = Gpost->discardCount[randPlayer];
    int postDiscardCount = 0;

    for (i = 0; i < 25; i++)
    {
        Gpost->supplyCount[i] = 0;  // set all supply counts to zero
    }
    int gainCardCase1 = gainCard(randSupplyPos, Gpost, 1, randPlayer); // all three cases try to gain card from empty pile
    int gainCardCase2 = gainCard(randSupplyPos, Gpost, 2, randPlayer);
    int gainCardCase3 = gainCard(randSupplyPos, Gpost, 3, randPlayer);
    assert(gainCardCase1 == -1);
    assert(gainCardCase2 == -1);
    assert(gainCardCase3 == -1);
    

    
    for (i = 0; i < 25; i++)
    {
        Gpost->supplyCount[i] = 5; // set all supply counts to five
    }
    
    for (int i = 1; i <=3; i++){
        if (i == 1) {  // added to player discard
            gainCardCase1 = gainCard(randSupplyPos, Gpost, i, randPlayer);
            postHandCount = (int)Gpost->handCount[randPlayer];
            postDeckCount = (int)Gpost->deckCount[randPlayer];
            postDiscardCount = (int)Gpost->discardCount[randPlayer];
            assert(gainCardCase1 != -1);
            assert(supplyCount(randSupplyPos, Gpost) == 4); // all supplies set to 5 before 1 removed
            assert(preHandCount == postHandCount);
            assert(preDeckCount == postDeckCount - 1); // card gained to deck (this case)
            assert(preDiscardCount == postDiscardCount);
        }
        if (i == 2) {  // added to player deck
            gainCardCase2 = gainCard(randSupplyPos, Gpost, i, randPlayer);
            postHandCount = (int)Gpost->handCount[randPlayer];
            postDeckCount = (int)Gpost->deckCount[randPlayer];
            postDiscardCount = (int)Gpost->discardCount[randPlayer];
            assert(gainCardCase2 != -1);
            assert(supplyCount(randSupplyPos, Gpost) == 3); // all supplies set to 5 before 1 + 1 removed
            assert(preHandCount == postHandCount - 1);  // card gained to hand (this case)
            assert(preDeckCount == postDeckCount - 1);  // card gained to deck (case 1 above)
            assert(preDiscardCount == postDiscardCount);
        }
        if (i == 3) {  // added to player hand
            gainCardCase3 = gainCard(randSupplyPos, Gpost, i, randPlayer);
            postHandCount = (int)Gpost->handCount[randPlayer];
            postDeckCount = (int)Gpost->deckCount[randPlayer];
            postDiscardCount = (int)Gpost->discardCount[randPlayer];
            assert(gainCardCase3 != -1);
            assert(supplyCount(randSupplyPos, Gpost) == 2); // all supplies set to 5 before 1 + 1 + 1 removed
            assert(preHandCount == postHandCount - 1);   // card gained to hand (case 2 above)
            assert(preDeckCount == postDeckCount - 1);   // card gained to deck (case 1 above)
            assert(preDiscardCount == postDiscardCount - 1);  // card gained to discard case 3 (this case)
        }
    }
}

/* checks to see that the prper coin count is returned for a random player with hand set to copper or silver or gold */
void checkUpdateCoins(){
    memcpy (Gpost, G, sizeof(struct gameState));
    int randPlayer = rand() % (Gpost->numPlayers);
    
    for (int metalNum = 4; metalNum <= 6; metalNum++){ // 4 = copper (x1 coin) , 5 = silver (x2 coins), 6 = gold (x3 coins)
        for (i = 0; i < Gpost->handCount[randPlayer]; i++)
        {
            Gpost->hand[randPlayer][i] = metalNum;  // set all to copper
        }
        updateCoins(randPlayer, Gpost, 0);
        assert(Gpost->coins == Gpost->handCount[randPlayer] * (metalNum - 3) );
    }
}


int main (int argc, char* argv[]) {
    
    for (int i = 0; i < NUM_TESTS; i++) {
        setUpGameState();   // create identical randomized game states for pre and post
        
        checkInitialGameState();
        checkShuffle();
        checkBuyCard();
        checkNumHandCards();
        checkHandCard();
        checkSupplyCount();
        checkFullDeckCount();
        checkWhoseTurn();
        checkEndTurn();
        checkIsGameOver();
        checkScoreFor();
        checkGetWinners();
        checkDrawCard();
        checkGetCost();
        checkDiscardCard();
        checkGainCard();
        checkUpdateCoins();
        printf ("DONE  >>>>>>>>>>>\n");
    }
    
    return 0;
}

